package org.vison.wonfu.framework.codestyle.rules.impl;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import org.vison.wonfu.framework.codestyle.config.CheckerConfig;
import org.vison.wonfu.framework.codestyle.issue.Issue;
import org.vison.wonfu.framework.codestyle.issue.IssueCollector;
import org.vison.wonfu.framework.codestyle.rules.CodeCheckRule;

import java.io.File;
import java.util.List;

public class IpoInterfacePropertyCheckRule implements CodeCheckRule {

    private static final String RULE_ID = "ipo-default-value";
    private static final String RULE_NAME = "IPO接口实现类属性默认值检查";
    private  String ipoClass = "IPO";
    private boolean enabled = true;
    private boolean strict = false;



    @Override
    public String getId() {
        return RULE_ID;
    }

    @Override
    public String getName() {
        return RULE_NAME;
    }

    @Override
    public String getDescription() {
        return "";
    }

    @Override
    public void initialize(CheckerConfig config) {
        this.enabled = config.isRuleEnabled(RULE_ID);
        this.ipoClass = config.getRuleProperty(RULE_ID, "ipoClass", String.class, ipoClass);
        this.strict = config.getRuleConfig(RULE_ID).isStrict();
    }

    @Override
    public boolean isStrict() {
        return strict;
    }

    @Override
    public void check(File file, CompilationUnit compilationUnit, IssueCollector collector) {
        if(!enabled) {
            return;
        }
        // 遍历所有类声明
        List<ClassOrInterfaceDeclaration> classes = compilationUnit.findAll(ClassOrInterfaceDeclaration.class);
        for (ClassOrInterfaceDeclaration classDecl : classes) {
            // 检查类是否实现了IPO接口
            if (!isImplementingIpoInterface(classDecl)) {
                continue;
            }
            List<FieldDeclaration> fields = classDecl.getFields();
            for (FieldDeclaration field : fields) {
                // 检查每个变量声明
                for (VariableDeclarator variable : field.getVariables()) {
                    // 判断是否有默认值
                    Expression initializer = variable.getInitializer().orElse(null);
                    if (initializer != null) {
                        // 收集问题
                        String message = String.format(
                                "实现IPO接口的类 '%s' 中的属性 '%s' 不能有默认值",
                                classDecl.getNameAsString(),
                                variable.getNameAsString()
                        );
                        int line = variable.getBegin().isPresent() ? variable.getBegin().get().line : 0;
                        collector.addIssue(new Issue(file, line, RULE_ID, message, Issue.Severity.ERROR));
                    }
                }
            }

        }

    }

    /**
     * 判断类是否实现了IPO接口
     */
    private boolean isImplementingIpoInterface(ClassOrInterfaceDeclaration clazz) {
        // 检查类实现的所有接口
        if(clazz.getImplementedTypes().isEmpty()){
            return false;
        }
        // 检查是否包含IPO接口（通过全限定名来判断
        return clazz.getImplementedTypes().stream()
                .anyMatch(type -> {
                    // 全限定名需要反射, type.resolve().asReferenceType().getQualifiedName()
                    // 这里只简单用SimpleName来判断 提取接口的原始名称（剥离泛型参数）
                    return getRawTypeName(type).equals(ipoClass);
                });
    }

    private String getRawTypeName (ClassOrInterfaceType type) {
        // 1. 处理泛型参数（如 <Long>、<T, K>）
        if (type.getTypeArguments().isPresent()) {
            // 清除泛型参数后获取类型名
            return type.getNameWithScope();
        }

        // 2. 非泛型类型直接返回
        return type.getNameAsString();
    }
}
